package com.hexingmo.dawn.lang;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @author He Xing Mo
 * @since 1.0
 */
public class Primitives {

    /**
     * 基本数据类型名称-类映射
     */
    public static final Map<String , Class<?>> PRIMITIVE_NAME_CLASS_MAP;

    /**
     * 基本数据类型-包装类映射
     */
    public static final Map<Class<?> , Class<?>> PRIMITIVE_WRAPPER_CLASS_MAP;

    /**
     * 基本数据类型-字节数映射
     */
    public static final Map<Class<?>, Integer> PRIMITIVE_BYTES_MAP;

    /**
     * 基本数据类型-比特数映射
     */
    public static final Map<Class<?>, Integer> PRIMITIVE_BITS_MAP;

    static {
        Map<String, Class<?>> primitiveNameClassMap = new HashMap<>();
        // 基本数据类型
        primitiveNameClassMap.put("boolean" ,Boolean.TYPE);
        primitiveNameClassMap.put("byte" , Byte.TYPE);
        primitiveNameClassMap.put("char" , Character.TYPE);
        primitiveNameClassMap.put("short" , Short.TYPE);
        primitiveNameClassMap.put("int" , Integer.TYPE);
        primitiveNameClassMap.put("long" , Long.TYPE);
        primitiveNameClassMap.put("float" , Float.TYPE);
        primitiveNameClassMap.put("double" , Double.TYPE);
        primitiveNameClassMap.put("void" , Void.TYPE);

        PRIMITIVE_NAME_CLASS_MAP = Collections.unmodifiableMap(primitiveNameClassMap);

        // 包装数据类型
        Map<Class<?>, Class<?>> primitiveWrapperClassMap = new HashMap<>();

        primitiveWrapperClassMap.put(boolean.class , Boolean.class);
        primitiveWrapperClassMap.put(char.class , Character.class);
        primitiveWrapperClassMap.put(byte.class , Byte.class);
        primitiveWrapperClassMap.put(short.class , Short.class);
        primitiveWrapperClassMap.put(int.class , Integer.class);
        primitiveWrapperClassMap.put(long.class , Long.class);
        primitiveWrapperClassMap.put(float.class , Float.class);
        primitiveWrapperClassMap.put(double.class , Double.class);
        primitiveWrapperClassMap.put(void.class , Void.class);
        PRIMITIVE_WRAPPER_CLASS_MAP = Collections.unmodifiableMap(primitiveWrapperClassMap);

        // 基本数据类型字节数映射
        Map<Class<?>, Integer> primitiveBytesMap = new HashMap<>();
        primitiveBytesMap.put(boolean.class, 1);
        primitiveBytesMap.put(byte.class, 1);
        primitiveBytesMap.put(char.class, 2);
        primitiveBytesMap.put(short.class, 2);
        primitiveBytesMap.put(int.class, 4);
        primitiveBytesMap.put(long.class, 8);
        primitiveBytesMap.put(float.class, 4);
        primitiveBytesMap.put(double.class, 8);
        primitiveBytesMap.put(void.class, 0);
        PRIMITIVE_BYTES_MAP = Collections.unmodifiableMap(primitiveBytesMap);

        // 基本数据类型比特数映射
        Map<Class<?>, Integer> primitiveBitsMap = new HashMap<>();
        primitiveBitsMap.put(boolean.class, 8);
        primitiveBitsMap.put(byte.class, 8);
        primitiveBitsMap.put(char.class, 16);
        primitiveBitsMap.put(short.class, 16);
        primitiveBitsMap.put(int.class, 32);
        primitiveBitsMap.put(long.class, 64);
        primitiveBitsMap.put(float.class, 32);
        primitiveBitsMap.put(double.class, 64);
        primitiveBitsMap.put(void.class, 0);
        PRIMITIVE_BITS_MAP = Collections.unmodifiableMap(primitiveBitsMap);
    }

    private Primitives() {
        throw new IllegalStateException("Static utility classes do not support instantiation");
    }

    /**
     * 检查给定的类是否为基本类型或其包装类。
     *
     * @param type 要检查的类
     * @return 如果类是基本类型或其包装类则返回 true，否则返回 false
     */
    public static boolean isPrimitiveOrWrapper(Class<?> type) {
        if (type == null) {
            return false;
        }
        return PRIMITIVE_WRAPPER_CLASS_MAP.containsKey(type) || PRIMITIVE_WRAPPER_CLASS_MAP.containsValue(type);
    }

    /**
     * 检查给定的类是否为基本类型。
     *
     * @param type 要检查的类
     * @return 如果类是基本类型则返回 true，否则返回 false
     */
    public static boolean isPrimitive(Class<?> type) {
        if (type == null) {
            return false;
        }
        return PRIMITIVE_NAME_CLASS_MAP.containsValue(type);
    }

    /**
     * 检查给定的类是否为基本类型的包装类。
     *
     * @param type 要检查的类
     * @return 如果类是基本类型的包装类则返回 true，否则返回 false
     */
    public static boolean isPrimitiveWrapper(Class<?> type) {
        if (type == null) {
            return false;
        }
        return PRIMITIVE_WRAPPER_CLASS_MAP.containsValue(type);
    }

    /**
     * 将 Boolean 对象拆箱为基本类型 boolean，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Boolean 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 boolean 值
     */
    public static boolean unboxing(Boolean value, boolean defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Character 对象拆箱为基本类型 char，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Character 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 char 值
     */
    public static char unboxing(Character value, char defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Byte 对象拆箱为基本类型 byte，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Byte 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 byte 值
     */
    public static byte unboxing(Byte value, byte defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Short 对象拆箱为基本类型 short，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Short 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 short 值
     */
    public static short unboxing(Short value, short defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Integer 对象拆箱为基本类型 int，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Integer 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 int 值
     */
    public static int unboxing(Integer value, int defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Long 对象拆箱为基本类型 long，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Long 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 long 值
     */
    public static long unboxing(Long value, long defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Float 对象拆箱为基本类型 float，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Float 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 float 值
     */
    public static float unboxing(Float value, float defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 将 Double 对象拆箱为基本类型 double，如果对象为 null 则返回默认值。
     *
     * @param value        要拆箱的 Double 对象
     * @param defaultValue 如果 value 为 null 时的默认返回值
     * @return 拆箱后的基本类型 double 值
     */
    public static double unboxing(Double value, double defaultValue) {
        return value == null ? defaultValue : value;
    }

    /**
     * 获取基本数据类型占用的字节数。
     *
     * @param type 基本数据类型
     * @return 占用的字节数，如果不是基本数据类型则返回 -1
     */
    public static int getBytes(Class<?> type) {
        if (type == null) {
            return -1;
        }
        return PRIMITIVE_BYTES_MAP.getOrDefault(type, -1);
    }

    /**
     * 获取基本数据类型占用的比特数。
     *
     * @param type 基本数据类型
     * @return 占用的比特数，如果不是基本数据类型则返回 -1
     */
    public static int getBits(Class<?> type) {
        if (type == null) {
            return -1;
        }
        return PRIMITIVE_BITS_MAP.getOrDefault(type, -1);
    }

    /**
     * 根据基本数据类型名称获取占用的字节数。
     *
     * @param typeName 基本数据类型名称（如 "int", "double" 等）
     * @return 占用的字节数，如果不是基本数据类型则返回 -1
     */
    public static int getBytes(String typeName) {
        if (typeName == null) {
            return -1;
        }
        Class<?> type = PRIMITIVE_NAME_CLASS_MAP.get(typeName);
        return type != null ? getBytes(type) : -1;
    }

    /**
     * 根据基本数据类型名称获取占用的比特数。
     *
     * @param typeName 基本数据类型名称（如 "int", "double" 等）
     * @return 占用的比特数，如果不是基本数据类型则返回 -1
     */
    public static int getBits(String typeName) {
        if (typeName == null) {
            return -1;
        }
        Class<?> type = PRIMITIVE_NAME_CLASS_MAP.get(typeName);
        return type != null ? getBits(type) : -1;
    }

    /**
     * 检查给定的类是否为基本数据类型。
     *
     * @param type 要检查的类
     * @return 如果类是基本数据类型则返回 true，否则返回 false
     */
    public static boolean isPrimitiveType(Class<?> type) {
        return type != null && PRIMITIVE_BYTES_MAP.containsKey(type);
    }

    /**
     * 检查给定的类型名称是否为基本数据类型。
     *
     * @param typeName 要检查的类型名称
     * @return 如果类型名称是基本数据类型则返回 true，否则返回 false
     */
    public static boolean isPrimitiveType(String typeName) {
        return typeName != null && PRIMITIVE_NAME_CLASS_MAP.containsKey(typeName);
    }

}
